﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmetic.DataEntity;

namespace Cosmetic.Logic
{
	/// <summary>
	/// forum, topic, post manager class
	/// </summary>
	public class ForumManager : LogicBase
    {
		private CategoryManager m_CategoryManager	= new CategoryManager();

		public enum ETopicState
		{
			Normal,
			Digest,
			BoardTop,
			ForumTop,
			Close
		}

		#region Forum

		/// <summary>
		/// insert a new forum into database
		/// </summary>
		/// <param name="aForum">a new forum</param>
		public void InsertForum(Forum aForum)
		{
			if (this.ForumExist(aForum.Title))
			{
				return;
			}

			if (aForum.Index == 0)
			{
				aForum.Index	= this.GetAllForum().Count + 1;
			}

			m_CosmeticDC.Forums.InsertOnSubmit(aForum);
			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// delete the forum and forum's all topics, forum's all posts
		/// </summary>
		/// <param name="aForum">the forum want delete</param>
		public void DeleteForum(Forum aForum)
		{
			List<Post> thePosts		= (from thePost in m_CosmeticDC.Posts
									   join theTopic in m_CosmeticDC.Topics on thePost.TopicId equals theTopic.TopicId 
									   where theTopic.ForumId == aForum.ForumId 
									   select thePost).ToList();
			m_CosmeticDC.Posts.DeleteAllOnSubmit(thePosts);
			//m_CosmeticDC.SubmitChanges();

			m_CosmeticDC.Topics.DeleteAllOnSubmit(aForum.Topics);
			//m_CosmeticDC.SubmitChanges();

			m_CosmeticDC.ForumAdmins.DeleteAllOnSubmit(aForum.ForumAdmins);
			//m_CosmeticDC.SubmitChanges();

			m_CosmeticDC.Forums.DeleteOnSubmit(aForum);
			m_CosmeticDC.SubmitChanges();
		}
		/// <summary>
		/// delete the forum and forum's all topics, forum's all posts
		/// </summary>
		/// <param name="aForumId">the forum want delete</param>
		public void DeleteForum(Guid aForumId)
		{
			this.DeleteForum(this.GetForumById(aForumId));
		}

		/// <summary>
		/// get forum by forum id
		/// </summary>
		/// <param name="aForumId">forum id</param>
		/// <returns>forum</returns>
		public Forum GetForumById(Guid aForumId)
		{
			return m_CosmeticDC.Forums.Single(theForum => theForum.ForumId == aForumId);
		}

		/// <summary>
		/// get all forum
		/// </summary>
		/// <returns>forum list</returns>
		public List<Forum> GetAllForum()
		{
			return m_CosmeticDC.Forums.OrderBy(theForum=>theForum.Index).ToList();
		}

		/// <summary>
		/// check the forum title whether or not exist.
		/// </summary>
		/// <param name="aForumTitle">the forum title wanna check</param>
		/// <returns>True: the forum title already exist. False: the forum title isnt exist.</returns>
		public bool ForumExist(string aForumTitle)
		{
			List<Forum> theForumList	= (from theForum in m_CosmeticDC.Forums 
										   where theForum.Title.Equals(aForumTitle) 
										   select theForum).ToList();
			return 0 != theForumList.Count;
		}

		/// <summary>
		/// check the user is or isnot the forum admin.
		/// </summary>
		/// <param name="aForumId">forum id</param>
		/// <param name="aUserId">user id</param>
		/// <returns>True: the user is the forum admin. False: the use is not the forum admin.</returns>
		public bool CheckForumAdmin(Guid aForumId, Guid aUserId)
		{
			List<ForumAdmin> theForumAdminList	= (from theForumAdmin in m_CosmeticDC.ForumAdmins
												   where theForumAdmin.UserId == aUserId && theForumAdmin.ForumId == aForumId
												   select theForumAdmin).ToList();

			return theForumAdminList.Count == 1;
		}

		/// <summary>
		/// set the use as the forum admin
		/// </summary>
		/// <param name="aForumId">forum id</param>
		/// <param name="aUserId">user id</param>
		public void SetFourmAdmin(Guid aForumId, Guid aUserId)
		{
			if (this.CheckForumAdmin(aForumId, aUserId))
			{
				return;
			}

			Forum theFourm	= this.GetForumById(aForumId);
			theFourm.ForumAdmins.Add(new ForumAdmin()
									{
										ForumAdminId	= Guid.NewGuid(),
										CreateTime		= DateTime.Now,
										UserId			= aUserId,
										ForumId			= aForumId										
									});

			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// remove the use from the forum admins
		/// </summary>
		/// <param name="aForumAdminId">forum admin id</param>
		public void RemoveFourmAdmin(Guid aForumAdminId)
		{
			List<ForumAdmin> theForumAdminList	= (from theForumAdmin in m_CosmeticDC.ForumAdmins 
												   where theForumAdmin.ForumAdminId == aForumAdminId 
												   select theForumAdmin).ToList();

			if (theForumAdminList.Count != 1)
			{
				return;
			}

			m_CosmeticDC.ForumAdmins.DeleteOnSubmit(theForumAdminList[0]);
			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// get the forum's admin
		/// </summary>
		/// <param name="aForumId">forum id</param>
		/// <returns>admin list</returns>
		public List<User> GetForumAdmin(Guid aForumId)
		{
			return (from theUser in m_CosmeticDC.Users 
			        join theForumAdmin in m_CosmeticDC.ForumAdmins on theUser.UserId equals theForumAdmin.UserId 
			        where theForumAdmin.ForumId == aForumId 
			        select theUser).ToList();
		}
		/// <summary>
		/// get the forum's admin
		/// </summary>
		/// <param name="aForum">forum</param>
		/// <returns>admin list</returns>
		public List<User> GetForumAdmin(Forum aForum)
		{
			return this.GetForumAdmin(aForum.ForumId);
		}

		#endregion





		#region Topic

		/// <summary>
		/// insert new topic into database
		/// </summary>
		/// <param name="aTopic">a new topic</param>
		public void InsertTopic(Topic aTopic)
		{
			m_CosmeticDC.Topics.InsertOnSubmit(aTopic);
			m_CosmeticDC.SubmitChanges();
		}
		/// <summary>
		/// insert new topic and post into database
		/// </summary>
		/// <param name="aTopic">Topic</param>
		/// <param name="aContent">post content</param>
		public void InsertTopic(Topic aTopic, string aContent)
		{
			Post theNewPost					= new Post();
			theNewPost.Content				= aContent;
			theNewPost.CreateTime			= aTopic.CreateTime;
			theNewPost.LastUpdateTime		= aTopic.LastUpdateTime;
			theNewPost.PostId				= Guid.NewGuid();
			theNewPost.Title				= aTopic.Title;
			theNewPost.TopicId				= aTopic.TopicId;
			theNewPost.User					= aTopic.User;
			aTopic.Posts.Add(theNewPost);

			m_CosmeticDC.Topics.InsertOnSubmit(aTopic);
			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// delete topic
		/// </summary>
		/// <param name="aTopic">the topic want delete</param>
		public void DeleteTopic(Topic aTopic)
		{
			m_CosmeticDC.Posts.DeleteAllOnSubmit(aTopic.Posts);
			m_CosmeticDC.SubmitChanges();

			m_CosmeticDC.Topics.DeleteOnSubmit(aTopic);
			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// get topics by forum
		/// </summary>
		/// <param name="aForum">the forum</param>
		/// <returns>topic list</returns>
		public List<Topic> GetTopicByForum(Forum aForum)
		{
			return this.GetTopicByForum(aForum.ForumId);
		}
		/// <summary>
		/// get topics by forum id
		/// </summary>
		/// <param name="aForumId">the forum id</param>
		/// <returns>topic list</returns>
		public List<Topic> GetTopicByForum(Guid aForumId)
		{
			return (from theTopic in m_CosmeticDC.Topics
					where theTopic.ForumId == aForumId
					orderby theTopic.CreateTime descending
					select theTopic).ToList();
		}
		/// <summary>
		/// get topic by forum and topic state
		/// </summary>
		/// <param name="aForumId">the forum id</param>
		/// <param name="aTopicState">topic state</param>
		/// <returns>topic list</returns>
		public List<Topic> GetTopicByForum(Guid aForumId, ETopicState aTopicState)
		{
			switch (aTopicState)
			{
				case ETopicState.Normal:
				default:
					return (from theTopic in m_CosmeticDC.Topics
							where (theTopic.TopicStateCategoryId == this.GetTopicStateByName(ETopicState.Normal).CategoryId
							|| theTopic.TopicStateCategoryId == this.GetTopicStateByName(ETopicState.Digest).CategoryId)
							&& theTopic.ForumId == aForumId
							orderby theTopic.CreateTime descending
							select theTopic).ToList();
					//break;
				case ETopicState.Digest:
				case ETopicState.BoardTop:
				case ETopicState.ForumTop:
				case ETopicState.Close:
					return (from theTopic in m_CosmeticDC.Topics
							where theTopic.TopicStateCategoryId == this.GetTopicStateByName(aTopicState).CategoryId
							&& theTopic.ForumId == aForumId
							orderby theTopic.CreateTime descending
							select theTopic).ToList();
			}
		}

		/// <summary>
		/// get topic by topic id
		/// </summary>
		/// <param name="aTopicId">the topic id</param>
		/// <returns>the topic</returns>
		public Topic GetTopicById(Guid aTopicId)
		{
			return m_CosmeticDC.Topics.Single(theTopic => theTopic.TopicId == aTopicId);
		}

		/// <summary>
		/// get all topic order by create time
		/// </summary>
		/// <returns>topic list</returns>
		public List<Topic> GetAllTopic()
		{
			return (from theTopic in m_CosmeticDC.Topics
					orderby theTopic.CreateTime descending
					select theTopic).ToList();
		}

		/// <summary>
		/// get topic state category by category name, if not find the category, create it.
		/// </summary>
		/// <param name="aTopicState">topic state category name</param>
		/// <returns>the topic state category</returns>
		public Category GetTopicStateByName(ETopicState aTopicState)
		{
			Category theTopicStateTopCategory	= this.m_CategoryManager.GetTopCategryByName(CategoryManager.ETopCategory.TopicState);
			List<Category> theCategoryList		= (from theCategory in m_CosmeticDC.Categories
													where theCategory.SupCategoryId == theTopicStateTopCategory.CategoryId && theCategory.Name == aTopicState.ToString()
													select theCategory).ToList();
			if (theCategoryList.Count == 0)
			{
				this.CheckTopicStateCategory();
				return this.GetTopicStateByName(aTopicState);
			}
			return theCategoryList[0];
		}
		
		/// <summary>
		/// check Topic State category whether or not exists. if not exists, create it.
		/// </summary>
		public void CheckTopicStateCategory()
		{
			Category theTopicStateTopCategory		= this.m_CategoryManager.GetTopCategryByName(CategoryManager.ETopCategory.TopicState);
			Type theTopicStateCategoryType			= typeof(ETopicState);
			foreach (string theTopicStateCategoryName in Enum.GetNames(theTopicStateCategoryType))
			{
				ETopicState theTopicStateCategoyEnum	= (ETopicState)Enum.Parse(typeof(ETopicState), theTopicStateCategoryName);
				List<Category> theCategoryList			= (from theCategory in m_CosmeticDC.Categories
															where theCategory.SupCategoryId == theTopicStateTopCategory.CategoryId && theCategory.Name == theTopicStateCategoyEnum.ToString()
															select theCategory).ToList();
				if (theCategoryList.Count == 0)
				{
					Category theCategory			= new Category();
					theCategory.Name				= theTopicStateCategoryName;
					theCategory.CategoryId			= Guid.NewGuid();
					theCategory.SupCategoryId		= theTopicStateTopCategory.CategoryId;
					theCategory.CreateTime			= DateTime.Now;
					this.m_CategoryManager.Insert(theCategory);
				}
			}
		}

		/// <summary>
		/// get topic by static from all topic.
		/// </summary>
		/// <param name="aTopicState">topic state</param>
		/// <returns>topic list</returns>
		public List<Topic> GetTopicByState(ETopicState aTopicState)
		{
			return (from theTopic in m_CosmeticDC.Topics
					where theTopic.TopicStateCategoryId == this.GetTopicStateByName(aTopicState).CategoryId
					orderby theTopic.CreateTime descending
					select theTopic).ToList();
		}

		#endregion





		#region Post

		/// <summary>
		/// insert a new post into database
		/// </summary>
		/// <param name="aPost">a new post</param>
		public void InsertPost(Post aPost)
		{
			m_CosmeticDC.Posts.InsertOnSubmit(aPost);
			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// delete the special post
		/// </summary>
		/// <param name="aPost">the post want delete</param>
		public void DeletePost(Post aPost)
		{
			m_CosmeticDC.Posts.DeleteOnSubmit(aPost);
			m_CosmeticDC.SubmitChanges();
		}

		/// <summary>
		/// get post by post id
		/// </summary>
		/// <param name="aPostId">post id</param>
		/// <returns>post</returns>
		public Post GetPostById(Guid aPostId)
		{
			return m_CosmeticDC.Posts.Single(thePost => thePost.PostId == aPostId);
		}

		/// <summary>
		/// get all post
		/// </summary>
		/// <returns>post list</returns>
		public List<Post> GetAllPost()
		{
			return m_CosmeticDC.Posts.ToList();
		}

		#endregion



	}
}
